package com.zenithmind.news.service.impl;

import com.zenithmind.news.pojo.vo.NewsVO;
import com.zenithmind.news.service.NewsCacheService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 新闻缓存服务实现类
 * 遵循单一职责原则：专门负责缓存操作
 * 遵循依赖倒置原则：实现抽象接口
 * 
 * @author ZenithMind Team
 * @since 2025-01-09
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class NewsCacheServiceImpl implements NewsCacheService {

    private final RedisTemplate<String, Object> redisTemplate;

    private static final String NEWS_CACHE_KEY = "news:detail:";
    private static final String HOT_NEWS_CACHE_KEY = "news:hot";
    private static final String NEWS_VIEW_COUNT_KEY = "news:view:";
    private static final String USER_PREFERENCES_KEY = "news:user:preferences:";

    @Override
    public void cacheNewsDetail(String newsId, NewsVO newsVO, long timeout, TimeUnit timeUnit) {
        try {
            String cacheKey = NEWS_CACHE_KEY + newsId;
            redisTemplate.opsForValue().set(cacheKey, newsVO, timeout, timeUnit);
            log.debug("缓存新闻详情：{}", newsId);
        } catch (Exception e) {
            log.error("缓存新闻详情失败：{}", newsId, e);
        }
    }

    @Override
    public NewsVO getCachedNewsDetail(String newsId) {
        try {
            String cacheKey = NEWS_CACHE_KEY + newsId;
            Object cached = redisTemplate.opsForValue().get(cacheKey);
            if (cached instanceof NewsVO) {
                log.debug("命中新闻详情缓存：{}", newsId);
                return (NewsVO) cached;
            }
        } catch (Exception e) {
            log.error("获取新闻详情缓存失败：{}", newsId, e);
        }
        return null;
    }

    @Override
    @SuppressWarnings("unchecked")
    public void cacheHotNews(List<NewsVO> newsList, long timeout, TimeUnit timeUnit) {
        try {
            redisTemplate.opsForValue().set(HOT_NEWS_CACHE_KEY, newsList, timeout, timeUnit);
            log.debug("缓存热门新闻列表，数量：{}", newsList.size());
        } catch (Exception e) {
            log.error("缓存热门新闻列表失败", e);
        }
    }

    @Override
    @SuppressWarnings("unchecked")
    public List<NewsVO> getCachedHotNews() {
        try {
            Object cached = redisTemplate.opsForValue().get(HOT_NEWS_CACHE_KEY);
            if (cached instanceof List) {
                log.debug("命中热门新闻缓存");
                return (List<NewsVO>) cached;
            }
        } catch (Exception e) {
            log.error("获取热门新闻缓存失败", e);
        }
        return null;
    }

    @Override
    public Long incrementViewCount(String newsId) {
        try {
            String cacheKey = NEWS_VIEW_COUNT_KEY + newsId;
            Long count = redisTemplate.opsForValue().increment(cacheKey);
            log.debug("增加新闻阅读量：{}，当前：{}", newsId, count);
            return count;
        } catch (Exception e) {
            log.error("增加新闻阅读量失败：{}", newsId, e);
            return 0L;
        }
    }

    @Override
    public void evictNewsCache(String newsId) {
        try {
            String detailKey = NEWS_CACHE_KEY + newsId;
            String viewKey = NEWS_VIEW_COUNT_KEY + newsId;
            redisTemplate.delete(detailKey);
            redisTemplate.delete(viewKey);
            // 清除热门新闻缓存，因为可能包含该新闻
            redisTemplate.delete(HOT_NEWS_CACHE_KEY);
            log.debug("清除新闻缓存：{}", newsId);
        } catch (Exception e) {
            log.error("清除新闻缓存失败：{}", newsId, e);
        }
    }

    @Override
    public void evictAllNewsCache() {
        try {
            // 使用模式匹配删除所有新闻相关缓存
            redisTemplate.delete(redisTemplate.keys(NEWS_CACHE_KEY + "*"));
            redisTemplate.delete(redisTemplate.keys(NEWS_VIEW_COUNT_KEY + "*"));
            redisTemplate.delete(HOT_NEWS_CACHE_KEY);
            log.info("清除所有新闻缓存");
        } catch (Exception e) {
            log.error("清除所有新闻缓存失败", e);
        }
    }

    @Override
    public void cacheUserPreferences(String userId, Object preferences, long timeout, TimeUnit timeUnit) {
        try {
            String cacheKey = USER_PREFERENCES_KEY + userId;
            redisTemplate.opsForValue().set(cacheKey, preferences, timeout, timeUnit);
            log.debug("缓存用户偏好：{}", userId);
        } catch (Exception e) {
            log.error("缓存用户偏好失败：{}", userId, e);
        }
    }

    @Override
    public Object getCachedUserPreferences(String userId) {
        try {
            String cacheKey = USER_PREFERENCES_KEY + userId;
            Object cached = redisTemplate.opsForValue().get(cacheKey);
            if (cached != null) {
                log.debug("命中用户偏好缓存：{}", userId);
                return cached;
            }
        } catch (Exception e) {
            log.error("获取用户偏好缓存失败：{}", userId, e);
        }
        return null;
    }
}
